"""
拼接指定目录中的子目录中的mp3文件
2025-02-25 07:24
"""
import os
import re
import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path

def natural_sort_key(s):
    """自然排序键函数，用于正确排序包含数字的文件名"""
    return [int(text) if text.isdigit() else text.lower()
            for text in re.split(r'(\d+)', s)]

def is_valid_date_dir(dir_name):
    """验证目录名是否为YYYY-MM-DD格式的日期"""
    return re.match(r'^\d{4}-\d{2}-\d{2}$', dir_name) is not None

def process_directory(subdir_path: Path, output_parent_dir: Path):
    """处理单个日期目录的MP3文件合并"""
    # 检查处理标记文件
    processed_flag = subdir_path / '.processed'
    if processed_flag.exists():
        return f"Skipped: {subdir_path.name}"

    # 收集所有MP3文件
    mp3_files = [f for f in subdir_path.iterdir() if f.suffix.lower() == '.mp3']
    if not mp3_files:
        return f"No MP3s: {subdir_path.name}"

    # 按自然顺序排序
    mp3_files.sort(key=lambda f: natural_sort_key(f.name))

    # 准备输入文件列表文件
    input_list_file = subdir_path / 'input_list.txt'
    with input_list_file.open('w') as f:
        for mp3 in mp3_files:
            f.write(f"file '{mp3.resolve()}'\n")

    # 从目录名中提取年份和月份
    year, month, _ = subdir_path.name.split('-')
    output_sub_dir = output_parent_dir / f"{year}-{month}"
    output_sub_dir.mkdir(parents=True, exist_ok=True)

    # 准备输出路径
    output_file = output_sub_dir / f"{subdir_path.name}.mp3"

    try:
        # 使用 ffmpeg 合并文件，屏蔽输出信息
        cmd = [
            'ffmpeg',
            '-f', 'concat',
            '-safe', '0',
            '-i', str(input_list_file),
            '-c', 'copy',
            str(output_file)
        ]
        subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)  # 屏蔽ffmpeg输出

        # 删除输入文件列表文件
        input_list_file.unlink()

        # 创建处理完成标记
        processed_flag.touch()
        return f"Merged: {subdir_path.name} ({len(mp3_files)} files) -> {output_file}"  # 增加输出路径信息
    except subprocess.CalledProcessError as e:
        # 清理可能生成的不完整文件
        if output_file.exists():
            output_file.unlink()
        return f"Error: {subdir_path.name} - {str(e)}"

def main():
    # 配置参数

    BASE_DIR = "~/Documents/lesson"
    CURRENT_DIR = Path(BASE_DIR).expanduser()
    SOURCE_DIR_NAME = "output"  # 需要处理的目录名
    source_dir = CURRENT_DIR / SOURCE_DIR_NAME

    if not source_dir.exists():
        print(f"Error: Source directory does not exist: {source_dir}")
        return

    # 获取所有日期子目录
    date_dirs = [entry for entry in source_dir.iterdir() if entry.is_dir() and is_valid_date_dir(entry.name)]

    # 设置输出目录到 CURRENT_DIR 目录下的
    output_dir = CURRENT_DIR
    output_dir.mkdir(exist_ok=True)

    # 使用线程池处理目录
    with ThreadPoolExecutor() as executor:
        futures = {executor.submit(process_directory, dir_path, output_dir): dir_path for dir_path in date_dirs}

        # 打印处理结果
        for future in as_completed(futures):
            dir_path = futures[future]
            try:
                result = future.result()
                print(result)
            except Exception as e:
                print(f"Error processing {dir_path}: {e}")

if __name__ == "__main__":
    main()
